/*
 *  Copyright 2007 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.webapp.taglib.core.logic;

import com.blandware.atleap.service.core.PageManager;
import com.blandware.atleap.common.Constants;
import com.blandware.atleap.common.util.QueryInfo;
import com.blandware.atleap.common.util.StringUtil;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.validator.GenericValidator;

/**
 * <p>This tag allows to iterate over pages fetched from the
 * persistence storage. You can supply prefix which page URIs must have,
 * ORDER BY clause, limit and offset; they will be treated as HQL treats.</p>
 * <p>
 * Full list of allowed attributes:
 * <ul>
 * <li>
 * <b>uriPrefix</b> - prefix from which page URI must start. If not specified,
 * all pages will be fetched.
 * </li>
 * <li>
 * <b>orderBy</b> - ORDER BY clause for HQL. If not specified, ORDER BY clause
 * will be empty.
 * </li>
 * <li>
 * <b>limit</b> - limit for HQL (maximum number of rows in result). If not
 * specified, limit clause is ignored (as no limit at all).
 * </li>
 * <li>
 * <b>offset</b> - offset for HQL (number of first row to output). If not
 * specified, offset clause is ignored (offset is very beginning).
 * </li>
 * <li>
 * <b>language</b> - locale identifier to use when getting page title. If not
 * specified, no language is used, title is not fetched.
 * </li>
 * <li>
 * <b>var</b> - name of scope variable that will accept object that corresponds
 * to current iteration. Must be specified.
 * </li>
 * <li>
 * <b>scope</b> - scope of variable to export current object
 * </li>
 * <li>
 * <b>createAction</b> - context-relative URI of Struts Action to call to create
 * a first element in collection
 * </li>
 * <li>
 * <b>createForward</b> - name of global Action Forward to use to create a first
 * element in collection
 * </li>
 * <li>
 * <b>createUri</b> - context-relative URI of action to call to create a first
 * element in collection
 * </li>
 * <li>
 * <b>ignore</b> - If "true", then if no pages were found, tag body will still
 * be rendered 1 time.
 * <br/>
 * If "false", then if no pages were found, then if site edit mode is ON and
 * there is some URL for creation of element, DIV will be rendered which allows
 * to create a page on double-click.
 * <br/>
 * This can be "true" or "false", default is "false".
 * </li>
 * </ul>
 * </p>
 * <p>When calculating create URI, firstly
 * <b>createAction</b> is considered, then (if it's <code>null</code>),
 * <b>createForward</b> is taken into account. If it's <code>null</code> too,
 * <b>createUri</b> is used. If all of them are <code>null</code>, there will
 * be no double-click wrapper.</p>
 * <p>
 * Here's an example:
 * <pre>
 * &lt;ul&gt;
 *     &lt;atleap:pageIterator
 *           uriPrefix="/pages/catalog/" var="page" orderBy="page.uri desc"&gt;
 *         &lt;li&gt;
 *             ${page.uri}
 *         &lt;/li&gt;
 *     &lt;/atleap:pageIterator&gt;
 * &lt;/ul&gt;
 * </pre>
 * This will produce a list of pages URIs, list elements will be ordered
 * descendingly by URI. Only content pages which are located in the 'catalog'
 * folder will be in list.
 * </p>
 * <p><a href="PageIteratorTag.java.html"><i>View source</i></a></p>
 *
 * @author Roman Puchkovskiy <a href="mailto:roman.puchkovskiy@blandware.com">
 *         &lt;roman.puchkovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.5 $ $Date: 2007/12/18 18:11:59 $
 * @jsp.tag name="pageIterator"
 * body-content="scriptless"
 */
public class PageIteratorTag extends BaseObjectIteratorTag {

    /**
     * Locale identifier to use when getting page title. If null, no locale
     * is used, title is not fetched.
     */
    protected String language = null;

    /**
     * Returns locale identifier to use when getting page title. If null, no
     * locale is used, title is not fetched.
     *
     * @return locale identifier
     * @see #language
     * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Locale identifier to use when getting page title"
     */
    public String getLanguage() {
        return language;
    }

    /**
     * Sets locale identifier to use when getting page title. If null, no
     * locale is used, title is not fetched.
     *
     * @param language identifier to set
     */
    public void setLanguage(String language) {
        this.language = language;
    }

    /**
     * Fetches collection to iterate over.
     *
     * @return collection
     */
    protected Collection fetchCollection() {
        String where = "";
        if (!GenericValidator.isBlankOrNull(uriPrefix)) {
            where = "page.uri like '" + StringUtil.sqlEscape(uriPrefix) + "%'";
        }

        PageManager manager = (PageManager) getBean(Constants.PAGE_MANAGER_BEAN);

        Map queryParameters = new HashMap();
        queryParameters.put("localeIdentifier", language);

        QueryInfo queryInfo = new QueryInfo();
        queryInfo.setWhereClause(where);
        queryInfo.setOrderByClause(orderBy);
        queryInfo.setLimit(limit);
        queryInfo.setOffset(offset);
        queryInfo.setQueryParameters(queryParameters);
        return manager.listPages(queryInfo);
    }

    /**
     * Returns resource key for message output in edit mode when nothing to
     * iterate.
     *
     * @return resource key
     */
    protected String getEmptyCollectionMessageKey() {
        return "core.commons.pageIterator.collectionIsEmpty";
    }
}
